package com.youzikeji.controller;

import com.google.common.util.concurrent.RateLimiter;
import com.youzikeji.service.OrderService;
import com.youzikeji.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.logging.LoggerGroup;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/stock")
@Slf4j
public class StockController {

    @Autowired
    private OrderService orderService;

    @Autowired
    private UserService userService;

    //创建令牌桶实例
    private RateLimiter rateLimiter = RateLimiter.create(50);


    //秒杀业务 —— 乐观锁
    @GetMapping("kill")
    public String kill(Integer id){
        log.info("秒杀商品的id = " + id);
        try {
            //根据秒杀的id，调用秒杀业务
//            //悲观锁
//            synchronized (this){
//                int orderId = orderService.kill(id);
//                return "秒杀成功，商品ID: " + String.valueOf(orderId);
//            }
            int orderId = orderService.kill(id);
            return "秒杀成功，商品ID: " + String.valueOf(orderId);
        }catch (Exception e){
            e.printStackTrace();
            return e.getMessage();
        }

    }

    //令牌桶方法限流demo
    @GetMapping("sale")
    public String sale(Integer id){
        //设置等待时间，超过时间没拿到令牌就抛弃，拿到了就处理
        if (!rateLimiter.tryAcquire(2, TimeUnit.SECONDS)){
            log.info("当前请求被限流，抛弃");
            return "抢购失败";
        }
        log.info("处理业务");
        return "抢购成功";
    }

    //乐观锁 + 令牌桶方法进行限流的秒杀业务
    @GetMapping("killByToken")
    public String killByToken(Integer id){
        log.info("秒杀商品的id = " + id);
        //加入令牌桶进行限流
        if (!rateLimiter.tryAcquire(3, TimeUnit.SECONDS)){
            log.info("当前请求被限流，抢购失败");
            return "抢购失败，当前秒杀活动过于火爆，请重试！！";
        }
        try {
            int orderId = orderService.kill(id);
            return "秒杀成功，商品ID: " + String.valueOf(orderId);
        }catch (Exception e){
            e.printStackTrace();
            return e.getMessage();
        }

    }

    //乐观锁 + 令牌桶方法进行限流的秒杀业务，同时加上一层MD5签名验证，隐藏秒杀接口
    @GetMapping("killByTokenAndMD5")
    public String killByTokenAndMD5(Integer id, Integer userId, String md5){
        log.info("秒杀商品的id = " + id);
        //加入令牌桶进行限流
        if (!rateLimiter.tryAcquire(3, TimeUnit.SECONDS)){
            log.info("当前请求被限流，抢购失败");
            return "抢购失败，当前秒杀活动过于火爆，请重试！！";
        }
        try {
            int orderId = orderService.kill(id, userId, md5);
            return "秒杀成功，商品ID: " + String.valueOf(orderId);
        }catch (Exception e){
            e.printStackTrace();
            return e.getMessage();
        }

    }

    //乐观锁 + 令牌桶方法进行限流的秒杀业务，同时加上一层MD5签名验证，隐藏秒杀接口，同时添加但用户访问频率限制
    @GetMapping("killByTokenAndMD5Limit")
    public String killByTokenAndMD5Limit(Integer id, Integer userId, String md5){
        log.info("秒杀商品的id = " + id);
        //加入令牌桶进行限流
        if (!rateLimiter.tryAcquire(3, TimeUnit.SECONDS)){
            log.info("当前请求被限流，抢购失败");
            return "抢购失败，当前秒杀活动过于火爆，请重试！！";
        }
        try {
            //单用户调用接口的频率限制
            int cnt = userService.saveUserCount(userId);
            log.info("用户截至为此的访问次数为: [{}]", cnt);
            boolean isBanned = userService.getUserCount(userId);
            if (isBanned) {
                log.info("购买失败，超过访问限制");
                return "购买失败，超过访问限制";
            }
            int orderId = orderService.kill(id, userId, md5);
            return "秒杀成功，商品ID: " + String.valueOf(orderId);
        }catch (Exception e){
            e.printStackTrace();
            return e.getMessage();
        }

    }

    @GetMapping("md5")
    public String md5(Integer id, Integer userId){
        String md5;
        try {
            md5 = orderService.getMd5(id, userId);
        } catch (Exception e){
            e.printStackTrace();
            return "获取md5失败：" + e.getMessage();
        }
        return "获取的Md5信息为: " + md5;
    }
}
